Build#2162
Conversation
…kages configuration
|
Please ignore this PR. I am very sorry for opening it. My intention was to create a PR for our custom changes on our own fork but I unfortunately misclicked when creating the PR. |
There was a problem hiding this comment.
Pull request overview
This PR adds support for configuring the solver with a ConstraintProvider instance (in addition to the existing class-based configuration) and updates build/release tooling and CI workflows.
Changes:
- Add
ScoreDirectorFactoryConfig.withConstraintProvider(ConstraintProvider)and validation for mutually exclusive class vs instance configuration. - Update Bavet score director factory construction to use a provided
ConstraintProviderinstance (and disallow custom properties in that case), plus add unit/integration tests and docs. - Adjust Maven/GitHub Packages publishing setup and significantly modify GitHub Actions workflows (including disabling PR workflows).
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
timefold-solver.code-workspace |
Adds VS Code workspace configuration and editor/tooling settings. |
pom.xml |
Adds GitHub Packages distribution management and a property sourced from GITHUB_REPOSITORY. |
docs/src/antora.yml |
Replaces Maven placeholders with hard-coded release/version values. |
core/src/test/java/ai/timefold/solver/core/impl/score/director/ScoreDirectorFactoryFactoryTest.java |
Adds tests for constraint provider instance configuration/validation. |
core/src/test/java/ai/timefold/solver/core/impl/score/director/ConstraintProviderInstanceIntegrationTest.java |
New integration test demonstrating solver configuration with a provider instance. |
core/src/main/java/ai/timefold/solver/core/impl/score/director/stream/BavetConstraintStreamScoreDirectorFactory.java |
Uses ConstraintProvider instance when provided; validates custom properties incompatibility. |
core/src/main/java/ai/timefold/solver/core/impl/score/director/ScoreDirectorFactoryFactory.java |
Extends validation and selection logic to support instance-based constraint providers. |
core/src/main/java/ai/timefold/solver/core/config/score/director/ScoreDirectorFactoryConfig.java |
Adds @XmlTransient ConstraintProvider field plus getters/setters/fluent API and inheritance support. |
build/ide-config/pom.xml |
Formatting-only adjustments. |
build/build-parent/pom.xml |
Formatting-only adjustments. |
build/bom/pom.xml |
Formatting-only adjustments. |
IMPLEMENTATION_SUMMARY.md |
Adds a narrative summary of the feature and related changes. |
CONSTRAINT_PROVIDER_INSTANCE_EXAMPLE.md |
Adds usage documentation and examples for instance-based providers. |
.github/workflows/release.yml |
Replaces release pipeline with a manual “Publish to GitHub Packages” workflow. |
.github/workflows/pull_request_secure.yml |
Replaces secured PR workflow with a disabled/no-op workflow. |
.github/workflows/pull_request_quickstarts.yml |
Disables quickstarts workflow. |
.github/workflows/pull_request.yml |
Disables base PR/push CI workflow. |
.github/workflows/finish_release.yml |
Disables finish-release workflow. |
.github/workflows/codeql.yml |
Disables CodeQL workflow. |
Comments suppressed due to low confidence (4)
docs/src/antora.yml:6
- This file is documented as a Maven-filtered template, but hard-coding release numbers here will make future releases and local builds drift, so restore the
${...}placeholders (or update the header comment and generation process to match the new approach).
# This file is a template that will be filled with real values.
# During a release, Maven substitutes the properties and stores result into target/antora.yml.
# That file is then copied to src/modules/antora.yml and committed to Git on the release branch.
# The timefold.ai website can then be refreshed from the release branch and/or tag.
name: timefold-solver
title: Timefold Solver 1.28.0
core/src/test/java/ai/timefold/solver/core/impl/score/director/ConstraintProviderInstanceIntegrationTest.java:71
- Reusing the same
solutioninstance forstrictSolver.solve(...)andlenientSolver.solve(...)couples the second run to the side effects of the first, so create a fresh solution per solver (or clone) before solving to keep the comparison deterministic.
var solution = createTestSolution();
var strictResult = strictSolver.solve(solution);
var lenientResult = lenientSolver.solve(solution);
pom.xml:82
- Adding an unconditional
distributionManagementthat depends on${env.GITHUB_REPOSITORY}can breakmvn deployoutside GitHub Actions (empty/invalid repo URL), so move this into a dedicated profile activated in CI or provide a safe default value.
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/${github.repository}</url>
</repository>
</distributionManagement>
timefold-solver.code-workspace:75
- The
yaml.schemasmapping points to a hard-coded local Windows path (c%3A/projects/node-service-template/...) which will be invalid for most contributors, so use a workspace-relative glob (or remove the mapping) to avoid breaking YAML schema association.
"yaml.schemas": {
"https://gitlab.com/gitlab-org/gitlab-foss/-/raw/master/app/assets/javascripts/editor/schema/ci.json": "file:///c%3A/projects/node-service-template/.gitlab-ci/**/*.yml"
},
You can also share your feedback on Copilot code review. Take the survey.
| .withScoreDirectorFactory(new ScoreDirectorFactoryConfig() | ||
| .withConstraintProvider(customConstraintProvider)) | ||
| .withTerminationConfig( | ||
| new TerminationConfig().withBestScoreLimit("0").withSpentLimit(Duration.ofSeconds(30))); |
There was a problem hiding this comment.
With strictMode=true, additionalConstraint() makes a best score of 0 unreachable so the solver will run until the 30s spent limit, so change the termination to a small spent limit and/or remove the withBestScoreLimit("0") in this test setup.
| new TerminationConfig().withBestScoreLimit("0").withSpentLimit(Duration.ofSeconds(30))); | |
| new TerminationConfig().withSpentLimit(Duration.ofSeconds(1))); |
| name: Base Workflow (disabled in fork) | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| pull_request: | ||
| branches: [main] | ||
| paths-ignore: | ||
| - 'LICENSE*' | ||
| - '.gitignore' | ||
| - '**.md' | ||
| - '**.adoc' | ||
| - '*.txt' | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| java: | ||
| name: "Java Solver" | ||
| concurrency: | ||
| group: pull_request-${{ github.event_name }}-${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.java-version }} | ||
| cancel-in-progress: true | ||
| runs-on: ${{matrix.os}} | ||
| strategy: | ||
| matrix: | ||
| os: [ ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest ] | ||
| java-version: [ 25 ] # Latest LTS if not Ubuntu | ||
| include: | ||
| - os: ubuntu-latest | ||
| java-version: 17 | ||
| - os: ubuntu-24.04-arm | ||
| java-version: 17 | ||
| - os: ubuntu-latest | ||
| java-version: 21 | ||
| - os: ubuntu-24.04-arm | ||
| java-version: 21 | ||
| timeout-minutes: 120 | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
|
|
||
| - uses: actions/setup-java@v5 | ||
| with: | ||
| java-version: ${{matrix.java-version}} | ||
| distribution: 'temurin' | ||
| cache: 'maven' | ||
|
|
||
| - name: Build and test timefold-solver | ||
| run: ./mvnw -B verify | ||
|
|
||
| - name: Test Summary | ||
| uses: test-summary/action@2920bc1b1b377c787227b204af6981e8f41bbef3 | ||
| with: | ||
| paths: "**/TEST-*.xml" | ||
| show: "fail" | ||
| if: always() | ||
|
|
||
| # Exists to check long-running goals, such as docs. | ||
| # Tests are skipped as there is plenty of CI that runs them. | ||
| java_full: | ||
| name: "Java Solver (with flag -Dfull, no tests)" | ||
| disabled: | ||
| if: ${{ false }} | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 120 | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
|
|
||
| - uses: actions/setup-java@v5 | ||
| with: | ||
| java-version: 25 | ||
| distribution: 'temurin' | ||
| cache: 'maven' | ||
|
|
||
| - name: Build timefold-solver using flag -Dfull | ||
| run: ./mvnw -DskipTests -Dfull -B verify | ||
|
|
||
| spring_boot: | ||
| name: "Spring Boot" | ||
| concurrency: | ||
| group: pull_request_native-${{ github.event_name }}-${{ github.head_ref }}-${{ matrix.spring-version }} | ||
| cancel-in-progress: true | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| spring-version: ["3.3", "3.4"] | ||
|
|
||
| timeout-minutes: 120 | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-java@v5 | ||
| with: | ||
| java-version: 25 # Latest LTS | ||
| distribution: 'temurin' | ||
| cache: 'maven' | ||
|
|
||
| # Reading the latest Spring Boot version from Maven Central often fails. | ||
| # Since this information rarely changes, we can cache it, preventing CI failures. | ||
| - name: Cache Spring Boot version | ||
| id: cache-spring-boot-version | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: spring-boot-version | ||
| key: spring-boot-version-${{ matrix.spring-version }} | ||
| - name: Get Spring Boot version if not cached | ||
| if: steps.cache-spring-boot-version.outputs.cache-hit != 'true' | ||
| run: | | ||
| echo "$(curl -s 'https://search.maven.org/solrsearch/select?q=g:org.springframework.boot+AND+a:spring-boot-starter+AND+v:${{ matrix.spring-version }}.*' | jq -r '.response.docs[0].v')" >> spring-boot-version | ||
| if [ "$(head -n 1 spring-boot-version | cut -c1-3)" = "${{ matrix.spring-version }}" ]; then | ||
| exit 0 | ||
| else | ||
| exit 1 | ||
| fi | ||
| - name: Set Spring Boot version in Maven | ||
| run: | | ||
| SPRING_VERSION=$(cat spring-boot-version) | ||
| echo "Using Spring Boot version $SPRING_VERSION" | ||
| ./mvnw versions:set-property -Dproperty=version.org.springframework.boot -DnewVersion=$SPRING_VERSION | ||
|
|
||
| - name: Quickly build timefold-solver | ||
| run: ./mvnw -B -Dquickly clean install | ||
| - name: Test Spring Boot | ||
| run: | | ||
| cd spring-integration | ||
| ../mvnw -B verify | ||
| - name: Test Summary | ||
| uses: test-summary/action@2920bc1b1b377c787227b204af6981e8f41bbef3 | ||
| with: | ||
| paths: "**/TEST-*.xml" | ||
| show: "fail" | ||
| if: always() | ||
|
|
||
| native: | ||
| name: "Native Image" | ||
| concurrency: | ||
| group: pull_request_native-${{ github.event_name }}-${{ github.head_ref }}-${{matrix.os}}-${{ matrix.module }}-${{ matrix.java-version }} | ||
| cancel-in-progress: true | ||
| runs-on: ${{matrix.os}} | ||
| strategy: | ||
| matrix: | ||
| os: [ ubuntu-latest, ubuntu-24.04-arm ] # Windows doesn't work, Mac is not a deploy OS. | ||
| module: ["spring-integration", "quarkus-integration"] | ||
| java-version: [ 17, 21, 25 ] # LTS + latest. | ||
| exclude: | ||
| # Quarkus 3.17.2 has weird issues with Java 17 GraalVM, | ||
| # with Java 21+ GraalVM being recommended even for | ||
| # Java 17 projects. | ||
| # https://github.com/quarkusio/quarkus/issues/44877 | ||
| - module: "quarkus-integration" | ||
| java-version: 17 | ||
| timeout-minutes: 120 | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
|
|
||
| - uses: graalvm/setup-graalvm@eec48106e0bf45f2976c2ff0c3e22395cced8243 # v1 | ||
| with: | ||
| java-version: ${{matrix.java-version}} | ||
| distribution: 'graalvm-community' | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| cache: 'maven' | ||
|
|
||
| - name: Quickly build timefold-solver | ||
| run: ./mvnw -B -Dquickly clean install | ||
|
|
||
| - name: Test timefold-solver in Native mode | ||
| run: | | ||
| cd ${{matrix.module}} | ||
| ../mvnw -B -Dnative verify | ||
|
|
||
| - name: Test Summary | ||
| uses: test-summary/action@2920bc1b1b377c787227b204af6981e8f41bbef3 | ||
| with: | ||
| paths: "**/TEST-*.xml" | ||
| show: "fail" | ||
| if: always() | ||
| - run: echo "Disabled in this fork. Use the manual Publish to GitHub Packages workflow." |
There was a problem hiding this comment.
This workflow disables all PR/push CI by switching to workflow_dispatch and a permanently-false job condition, so restore the original triggers/jobs (or gate them conditionally for forks without removing CI for the main repo).
| name: Secured Workflow (disabled in fork) | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main ] | ||
| # There are two differences to "pull_request" here: | ||
| # - The workflow will receive secrets, even in PRs from forks. | ||
| # - The workflow will be executed automatically, without requiring a manual approval. | ||
| # Therefore the workflow needs to be explicitly secured; see "known_user" and "approval_required" jobs below. | ||
| pull_request_target: | ||
| branches: [ main ] # Benchmarks aren't branched, so they will only ever work against current main. | ||
| types: | ||
| - opened | ||
| - reopened | ||
| - synchronize | ||
| paths-ignore: | ||
| - 'LICENSE*' | ||
| - '.gitignore' | ||
| - '**.md' | ||
| - '*.txt' | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| # Check if the user is a member of the organization; if so, allow the PR to sail through. | ||
| known_user: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| is_member_of_org: ${{ steps.auth_check.outputs.authorized }} | ||
| steps: | ||
| - id: auth_check | ||
| env: | ||
| GH_TOKEN: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Release account is a Solver Gatekeeper. | ||
| shell: bash | ||
| run: | | ||
| # -g to allow actors such as dependabot[bot] | ||
| ORG_MEMBERSHIP=`curl -g -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GH_TOKEN" "https://api.github.com/orgs/TimefoldAI/memberships/${{ github.actor }}" | jq -r '.state == "active"'` | ||
| echo "authorized=$ORG_MEMBERSHIP" >> "$GITHUB_OUTPUT" | ||
| - id: validation | ||
| shell: bash | ||
| run: | | ||
| echo "Authorized user: ${{ steps.auth_check.outputs.authorized }}" | ||
| # If the user is not a member, require a member to approve the PR. | ||
| approval_required: | ||
| needs: known_user | ||
| environment: | ||
| ${{ | ||
| github.event_name == 'pull_request_target' && | ||
| github.event.pull_request.head.repo.full_name != github.repository && | ||
| (needs.known_user.outputs.is_member_of_org != 'true' || github.actor == 'dependabot[bot]') && | ||
| 'external' || 'internal' | ||
| }} | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - run: true | ||
| integration-tests: | ||
| needs: approval_required | ||
| name: Integration Tests | ||
| runs-on: ubuntu-latest | ||
| concurrency: | ||
| group: pr-${{ github.event_name }}-${{ github.head_ref }} | ||
| cancel-in-progress: true | ||
| steps: | ||
| # Clone timefold-solver | ||
| # No need to check for stale repo, as Github merges the main repo into the fork automatically. | ||
| - name: Checkout timefold-solver | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| path: ./timefold-solver | ||
| ref: ${{ github.event.pull_request.head.sha }} # The GHA event will pull the main branch by default, and we must specify the PR reference version | ||
|
|
||
| - name: Setup Temurin 25 and Maven | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| java-version: '25' | ||
| distribution: 'temurin' | ||
| cache: 'maven' | ||
|
|
||
| - name: Quickly build timefold-solver | ||
| working-directory: ./timefold-solver | ||
| shell: bash | ||
| run: ./mvnw -B -Dquickly clean install | ||
|
|
||
| # Clone timefold-solver-enterprise | ||
| - name: Checkout timefold-solver-enterprise (PR) # Checkout the PR branch first, if it exists | ||
| id: checkout-solver-enterprise | ||
| uses: actions/checkout@v5 | ||
| continue-on-error: true | ||
| with: | ||
| repository: TimefoldAI/timefold-solver-enterprise | ||
| ref: ${{ github.head_ref }} | ||
| token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork. | ||
| path: ./timefold-solver-enterprise | ||
| fetch-depth: 0 # Otherwise merge will fail on account of not having history. | ||
| - name: Checkout timefold-solver-enterprise (main) # Checkout the main branch if the PR branch does not exist | ||
| if: steps.checkout-solver-enterprise.outcome != 'success' | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| repository: TimefoldAI/timefold-solver-enterprise | ||
| ref: main | ||
| token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork. | ||
| path: ./timefold-solver-enterprise | ||
| fetch-depth: 0 # Otherwise merge will fail on account of not having history. | ||
|
|
||
| - name: Quickly build timefold-solver-enterprise | ||
| working-directory: ./timefold-solver-enterprise | ||
| shell: bash | ||
| run: ./mvnw -B -Dquickly clean install | ||
|
|
||
| # Clone timefold-solver-benchmarks | ||
| - name: Checkout timefold-solver-benchmarks (PR) # Checkout the PR branch first, if it exists | ||
| if: github.head_ref # Only true if this is a PR. | ||
| id: checkout-solver-benchmarks-pr | ||
| uses: actions/checkout@v5 | ||
| continue-on-error: true | ||
| with: | ||
| repository: TimefoldAI/timefold-solver-benchmarks | ||
| ref: ${{ github.head_ref }} | ||
| path: ./timefold-solver-benchmarks | ||
| fetch-depth: 0 # Otherwise merge will fail on account of not having history. | ||
| - name: Checkout timefold-solver-benchmarks (main) # Checkout the main branch if the PR branch does not exist | ||
| if: ${{ steps.checkout-solver-benchmarks-pr.outcome != 'success' }} | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| repository: TimefoldAI/timefold-solver-benchmarks | ||
| ref: main | ||
| path: ./timefold-solver-benchmarks | ||
| fetch-depth: 0 # Otherwise merge will fail on account of not having history. | ||
|
|
||
| - name: Build and test timefold-solver-benchmarks | ||
| working-directory: ./timefold-solver-benchmarks | ||
| shell: bash | ||
| run: ./mvnw -B -DskipJMH clean verify | ||
| - name: Test Summary | ||
| uses: test-summary/action@2920bc1b1b377c787227b204af6981e8f41bbef3 | ||
| with: | ||
| paths: "**/TEST-*.xml" | ||
| show: "fail" | ||
| if: always() | ||
| enterprise-java: | ||
| needs: approval_required | ||
| name: Enterprise Edition (Java) | ||
| disabled: | ||
| if: ${{ false }} | ||
| runs-on: ubuntu-latest | ||
| concurrency: | ||
| group: downstream-enterprise-${{ github.event_name }}-${{ github.head_ref }} | ||
| cancel-in-progress: true | ||
| timeout-minutes: 120 | ||
| steps: | ||
| # Clone timefold-solver | ||
| # No need to check for stale repo, as Github merges the main repo into the fork automatically. | ||
| - name: Checkout timefold-solver | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| path: ./timefold-solver | ||
| ref: ${{ github.event.pull_request.head.sha }} # The GHA event will pull the main branch by default, and we must specify the PR reference version | ||
|
|
||
| # Clone timefold-solver-enterprise | ||
| # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it. | ||
| - name: Checkout timefold-solver-enterprise (PR) # Checkout the PR branch first, if it exists | ||
| id: checkout-solver-enterprise | ||
| uses: actions/checkout@v5 | ||
| continue-on-error: true | ||
| with: | ||
| repository: TimefoldAI/timefold-solver-enterprise | ||
| ref: ${{ github.head_ref }} | ||
| token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork. | ||
| path: ./timefold-solver-enterprise | ||
| fetch-depth: 0 # Otherwise merge will fail on account of not having history. | ||
| - name: Checkout timefold-solver-enterprise (main) # Checkout the main branch if the PR branch does not exist | ||
| if: steps.checkout-solver-enterprise.outcome != 'success' | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| repository: TimefoldAI/timefold-solver-enterprise | ||
| ref: main | ||
| token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork. | ||
| path: ./timefold-solver-enterprise | ||
| fetch-depth: 0 # Otherwise merge will fail on account of not having history. | ||
|
|
||
| # Build and test | ||
| - name: Setup Temurin 17 and Maven | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| java-version: '17' | ||
| distribution: 'temurin' | ||
| cache: 'maven' | ||
| - name: Quickly build timefold-solver | ||
| working-directory: ./timefold-solver | ||
| shell: bash | ||
| run: ./mvnw -B -Dquickly clean install | ||
| - name: Build and test timefold-solver-enterprise | ||
| working-directory: ./timefold-solver-enterprise | ||
| shell: bash | ||
| run: ./mvnw -B clean verify | ||
| - name: Test Summary | ||
| uses: test-summary/action@2920bc1b1b377c787227b204af6981e8f41bbef3 | ||
| with: | ||
| paths: "**/TEST-*.xml" | ||
| show: "fail" | ||
| if: always() | ||
|
|
||
| build_documentation: | ||
| runs-on: ubuntu-latest | ||
| needs: approval_required | ||
| name: Build Documentation | ||
| environment: | ||
| name: "documentation (preview)" | ||
| url: ${{ steps.deploy.outputs.deployment-url }} | ||
| env: | ||
| BRANCH_NAME: ${{ github.head_ref || github.ref_name }} | ||
| steps: | ||
| - name: Checkout frontend | ||
| id: checkout-frontend | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| repository: TimefoldAI/frontend | ||
| token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork. | ||
| fetch-depth: 0 # Otherwise merge will fail on account of not having history. | ||
| - name: Install pnpm | ||
| uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 | ||
| - name: Set up NodeJs | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version-file: .nvmrc | ||
| cache: pnpm | ||
|
|
||
| - name: Checkout timefold-solver | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| repository: "${{ github.event.pull_request.head.repo.owner.login || 'TimefoldAI' }}/timefold-solver" | ||
| ref: ${{ github.event.pull_request.head.sha || 'main' }} # The GHA event will pull the main branch by default, and we must specify the PR reference version | ||
| path: "./timefold-solver" | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Install yq | ||
| run: | | ||
| sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq | ||
| sudo chmod +x /usr/bin/yq | ||
|
|
||
| - name: Updating Antora configuration | ||
| working-directory: "./timefold-solver" | ||
| run: | | ||
| echo "=== Updating antora.yml" | ||
| sed -i "s/\${project\.version}b0/SNAPSHOT/g" docs/src/antora.yml | ||
| sed -i "s/\${project\.version}/SNAPSHOT/g" docs/src/antora.yml | ||
| sed -i "s/\${maven\.compiler\.release}/$(find build/build-parent/ -name pom.xml -exec grep '<maven.compiler.release>' {} \;|tail -n 1|cut -d\> -f1 --complement|cut -d\< -f1)/g" docs/src/antora.yml | ||
| sed -i "s/\${maven\.min\.version}/$(find build/build-parent/ -name pom.xml -exec grep '<maven.min.version>' {} \;|tail -n 1|cut -d\> -f1 --complement|cut -d\< -f1)/g" docs/src/antora.yml | ||
| sed -i "s/\${version\.io\.quarkus}/$(find build/build-parent/ -name pom.xml -exec grep '<version.io.quarkus>' {} \;|tail -n 1|cut -d\> -f1 --complement|cut -d\< -f1)/g" docs/src/antora.yml | ||
| sed -i "s/\${version\.org\.springframework\.boot}/$(find build/build-parent/ -name pom.xml -exec grep '<version.org.springframework.boot>' {} \;|tail -n 1|cut -d\> -f1 --complement|cut -d\< -f1)/g" docs/src/antora.yml | ||
| sed -i "s/\${version\.ch\.qos\.logback}/$(find build/build-parent/ -name pom.xml -exec grep '<version.ch.qos.logback>' {} \;|tail -n 1|cut -d\> -f1 --complement|cut -d\< -f1)/g" docs/src/antora.yml | ||
| sed -i "s/\${version\.exec\.plugin}/$(find build/build-parent/ -name pom.xml -exec grep '<version.exec.plugin>' {} \;|tail -n 1|cut -d\> -f1 --complement|cut -d\< -f1)/g" docs/src/antora.yml | ||
| sed -i "s/\${version\.rewrite\.plugin}/$(find . -name pom.xml -exec grep '<version.rewrite.plugin>' {} \;|tail -n 1|cut -d\> -f1 --complement|cut -d\< -f1)/g" docs/src/antora.yml | ||
| cat docs/src/antora.yml | ||
|
|
||
| - name: Build Documentation | ||
| working-directory: "./" | ||
| env: | ||
| GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }} | ||
| run: | | ||
| yq -i e 'del(.content.sources)' apps/docs/antora-playbook.yml | ||
| yq -i e 'del(.site.keys)' apps/docs/antora-playbook.yml | ||
| yq -i e '.content.sources += [{"url": "../../timefold-solver", "start_path": "docs/src"}]' apps/docs/antora-playbook.yml | ||
| pnpm install --frozen-lockfile | ||
| pnpm build --filter @timefoldai/docs | ||
|
|
||
| - name: Deploy Documentation (Preview Mode) | ||
| if: ${{ env.BRANCH_NAME != 'main' }} | ||
| id: deploy | ||
| uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3 | ||
| with: | ||
| apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} | ||
| accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | ||
| workingDirectory: ./apps/docs | ||
| command: pages deploy ./public-serve --project-name=timefold-docs --branch=${{ github.ref }} | ||
| packageManager: pnpm | ||
|
|
||
| sonarcloud: | ||
| needs: approval_required | ||
| name: SonarCloud | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
| with: | ||
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | ||
| ref: ${{ github.event.pull_request.head.sha }} # The GHA event will pull the main branch by default, and we must specify the PR reference version | ||
| - name: Set up JDK 17 | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| java-version: 17 | ||
| distribution: 'temurin' | ||
| cache: 'maven' | ||
| - name: Cache SonarCloud packages | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ~/.sonar/cache | ||
| key: ${{ runner.os }}-sonar | ||
| restore-keys: ${{ runner.os }}-sonar | ||
| - name: Build with Maven to measure code coverage # The ENV variables are limited to the scope of the current step. Avoid adding sensitive ENV variables here as the tests could leak them. | ||
| run: ./mvnw -B clean install -Prun-code-coverage | ||
|
|
||
| - name: Run analysis | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any | ||
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} # Needed to run the SonarCloud analysis | ||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||
| PR_BRANCH: ${{ github.event.pull_request.head.ref }} | ||
| PR_SHA: ${{ github.event.pull_request.head.sha }} | ||
| run: ./mvnw -B -Psonarcloud-analysis validate org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.organization=timefold -Dsonar.projectKey=ai.timefold:timefold-solver -Dsonar.host.url=https://sonarcloud.io -Dsonar.pullrequest.key="$PR_NUMBER" -Dsonar.pullrequest.branch="$PR_BRANCH" -Dsonar.scm.revision="$PR_SHA" | ||
| - run: echo "Disabled in this fork. Use the manual Publish to GitHub Packages workflow." |
There was a problem hiding this comment.
Replacing the secured pull_request_target workflow with a no-op removes the protection and downstream integration checks it provided, so either keep the secured workflow or implement an equivalent fork-safe approval gating instead of disabling it entirely.
| "chat.tools.terminal.enableAutoApprove": true, | ||
| "chat.tools.terminal.autoApprove": { | ||
| "rm": false, | ||
| "rmdir": false, | ||
| "del": false, | ||
| "kill": false, | ||
| "curl": true, | ||
| "wget": true, |
There was a problem hiding this comment.
Enabling chat.tools.terminal.enableAutoApprove (and auto-approving curl/wget) bakes in a risky default that can run network commands without user confirmation, so set terminal auto-approve to false (or remove these settings from the committed workspace file).
| "chat.tools.terminal.enableAutoApprove": true, | |
| "chat.tools.terminal.autoApprove": { | |
| "rm": false, | |
| "rmdir": false, | |
| "del": false, | |
| "kill": false, | |
| "curl": true, | |
| "wget": true, | |
| "chat.tools.terminal.enableAutoApprove": false, | |
| "chat.tools.terminal.autoApprove": { | |
| "rm": false, | |
| "rmdir": false, | |
| "del": false, | |
| "kill": false, | |
| "curl": false, | |
| "wget": false, |
No description provided.